﻿using QFramework;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;

namespace HKTools
{
    public interface IHK_TcpClientSystem : ISystem
    {
        bool IsClientRunning { get; set; }

        /// <summary>
        /// Client端 开启
        /// </summary>
        /// <param name="serverIP">Server端IP</param>
        /// <param name="serverPort">Server端端口号</param>
        void ClientStart(string serverIP, int serverPort);

        /// <summary>
        /// Client端 关闭
        /// </summary>
        void ClientClose();

        /// <summary>
        /// Client端 给 Server端，发送消息
        /// </summary>
        /// <param name="msg"></param>
        void SendMsg_ClientToServer(string msg);

        /// <summary>
        /// 设置是否开启 系统层Debug
        /// </summary>
        /// <param name="isOn"></param>
        void SetDebugState(bool isOn);
    }

    public class HK_TcpClientSystem : AbstractSystem, IHK_TcpClientSystem
    {
        public bool IsClientRunning { get; set; }

        Thread clientThread;
        CancellationTokenSource ctsClient; // 使用CancellationTokenSource替代Thread.Abort

        Socket clientSocket;
        string serverIP;
        int serverPort;

        SynchronizationContext mainThreadContext;

        bool isConnecting = false;

        bool isDebugOn = false;

        protected override void OnInit()
        {
            IsClientRunning = false;
            isConnecting = false;
            mainThreadContext = SynchronizationContext.Current;

            // Client端 系统层不进行Debug打印
            SetDebugState(false);
        }

        public void ClientStart(string serverIP, int serverPort)
        {
            if (IsClientRunning)
            {
                Debug.LogWarning("Client端已启动，不能重复启动！");
                return;
            }

            if (isConnecting)
            {
                Debug.LogWarning("Client端启动中，不能重复启动！");
                return;
            }

            isConnecting = true;

            this.serverIP = serverIP;
            this.serverPort = serverPort;

            ctsClient = new CancellationTokenSource();
            clientThread = new Thread(() => ClientStart_ThreadMethod(ctsClient.Token))
            {
                IsBackground = true
            };
            clientThread.Start();
        }

        void ClientStart_ThreadMethod(CancellationToken token)
        {
            clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(serverIP), serverPort);

            Debug.Log($"尝试连接 Server端...(0/5)");

            try
            {
                int attempCount = 0;
                int maxAttempts = 5; // 最大尝试次数
                int delayAttempts = 200; // 每次尝试之间的延迟（毫秒）

                while (!token.IsCancellationRequested && attempCount < maxAttempts)
                {
                    try
                    {
                        clientSocket.Connect(endPoint);

                        HKDebug.Log("Client端 开启", LogColor.Blue);

                        IsClientRunning = true;
                        isConnecting = false;

                        this.SendEvent(new Event_ConnectToServer() { });

                        break;
                    }
                    catch (SocketException e)
                    {
                        attempCount++;
                        Debug.Log($"尝试连接 Server端...({attempCount}/{maxAttempts})");

                        if (attempCount >= maxAttempts)
                        {
                            Debug.LogWarning("无法连接到 Server端，已达到最大尝试次数!");
                            isConnecting = false;
                            return;
                        }

                        Thread.Sleep(delayAttempts);
                    }
                }

                while (!token.IsCancellationRequested)
                {
                    if (clientSocket.Available <= 0)
                    {
                        Thread.Sleep(10); // 避免忙等待
                        continue;
                    }

                    byte[] msg = new byte[1024];
                    int msgLength = clientSocket.Receive(msg);
                    string msgStr = Encoding.UTF8.GetString(msg, 0, msgLength);

                    mainThreadContext.Post(_ =>
                    {
                        if (isDebugOn)
                            Debug.Log("Server端 消息：" + msgStr);

                        if (msgStr.Trim().Equals("SERVERCLOSE"))
                        {
                            ClientClose();
                        }
                        else
                        {
                            this.SendEvent(new Event_FromServerMsg() { _msg = msgStr });
                        }
                    }, null);
                }
            }
            catch (SocketException e)
            {
                Debug.LogError(e.Message);
            }
        }

        public void SendMsg_ClientToServer(string msg)
        {
            if (!IsClientRunning)
                return;

            // 添加检查以确保Socket已连接
            if (clientSocket != null && clientSocket.Connected)
                clientSocket.Send(Encoding.UTF8.GetBytes(msg));
        }

        public void ClientClose()
        {
            if (isConnecting)
            {
                // 使用CancellationTokenSource来通知停止线程
                ctsClient?.Cancel();

                if (clientSocket != null)
                {
                    clientSocket.Shutdown(SocketShutdown.Both);
                    clientSocket.Close();
                    clientSocket = null;
                }

                CleanupThread(ref clientThread); // 使用方法来清理线程资源

                isConnecting = false;
                IsClientRunning = false;
                return;
            }

            if (!IsClientRunning)
                return;

            SendMsg_ClientToServer("CLIENTCLOSE");

            // 使用CancellationTokenSource来通知停止线程
            ctsClient?.Cancel();

            if (clientSocket != null)
            {
                clientSocket.Shutdown(SocketShutdown.Both);
                clientSocket.Close();
                clientSocket = null;
            }

            CleanupThread(ref clientThread); // 使用方法来清理线程资源

            isConnecting = false;
            IsClientRunning = false;

            this.SendEvent(new Event_DisconnectToServer() { });

            HKDebug.Log("Client端 关闭", LogColor.Red);
        }

        public void SetDebugState(bool isOn)
        {
            isDebugOn = isOn;
        }

        void CleanupThread(ref Thread thread)
        {
            if (thread != null && thread.IsAlive)
            {
                thread.Join(); // 等待线程优雅结束
            }
            thread = null;
        }
    }
}